#pragma once

#include <Hazal.h>
#include <imgui.h>
#include <imgui_internal.h>

namespace Hazal
{
	class CSceneHierarchyPanel
	{
		friend class CScene;

	public:
		CSceneHierarchyPanel() = default;

		CSceneHierarchyPanel(const Ref<CScene>& rScene);

	public:
		/// <summary>
		/// 设置绘制面板的上下文场景
		/// </summary>
		/// <param name="rScene"></param>
		void SetContext(const Ref<CScene>& rScene);

		/// <summary>
		/// 绘制ImGui层次面板
		/// </summary>
		void OnImGuiRender();

		/// <summary>
		/// 获取当前选中的实体
		/// </summary>
		/// <returns></returns>
		CEntity GetSelectedEntity();

		/// <summary>
		/// 设置被选中实体
		/// </summary>
		void SetSelectedEntity(CEntity& entity);

	private:
		/// <summary>
		/// 绘制实体节点
		/// </summary>
		/// <param name="entity"></param>
		void DrawEntiyNode(CEntity& entity);

		/// <summary>
		/// 绘制实体包含的多个组件
		/// </summary>
		/// <param name="entity"></param>
		void DrawComponents(CEntity& entity);

		/// <summary>
		/// 绘制单个组件
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="strComponentName"></param>
		template<typename T>
		void DrawComponent(const std::string& strComponentName, CEntity& entity, std::function<void()> func)
		{
			/// ImGuiTreeNodeFlags_AllowItemOverlap - 允许后续小部件与此小部件重叠
			const ImGuiTreeNodeFlags treeNodeFlags = ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_AllowItemOverlap | 
														ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_SpanAvailWidth;

			float fContentRegionAvail = ImGui::GetContentRegionAvail().x;	///< 获取窗口宽度而非TreeNodeItem宽度
			ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { 4, 4 });
			ImGui::Separator();
			if (ImGui::TreeNodeEx((void*)typeid(T).hash_code(), treeNodeFlags, strComponentName.c_str()))
			{
				float fLinkHeight = GImGui->Font->FontSize + GImGui->Style.FramePadding.y * 2;
				ImGui::PopStyleVar();

				ImGui::SameLine(fContentRegionAvail - fLinkHeight * 0.5f);
				if (ImGui::Button("+", { fLinkHeight, fLinkHeight }))
				{
					ImGui::OpenPopup("ComponentSettings");
				}

				bool bRemoveComponent = false;
				if (ImGui::BeginPopup("ComponentSettings"))
				{
					if (ImGui::MenuItem("Remove component"))
					{
						bRemoveComponent = true;
					}

					ImGui::EndPopup();
				}

				func();

				if (bRemoveComponent)
				{
					entity.RemoveComponent<T>();
				}

				ImGui::TreePop();
			}
		}

	private:
		Ref<CScene> m_pContext;

		CEntity m_selectedEntity;

	};
}
